package com.tencent.wework;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.FileCopyUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Objects;

/**
 * 腾讯企业微信
 * <p></p>
 * <a href="https://developer.work.weixin.qq.com/document/path/91774">会话存档SDK</a>
 * 注意：这里包名不能变
 *
 * @author youfang
 * @version [1.0.0, 2022/1/13 19:53]
 **/
@Slf4j
public class Finance {

    public native static long NewSdk();

    /**
     * 初始化函数
     * Return值=0表示该API调用成功
     *
     * @param [in] sdk			NewSdk返回的sdk指针
     * @param [in] corpid      调用企业的企业id，例如：wwd08c8exxxx5ab44d，可以在企业微信管理端--我的企业--企业信息查看
     * @param [in] secret		聊天内容存档的Secret，可以在企业微信管理端--管理工具--聊天内容存档查看
     * @return 返回是否初始化成功
     * 0   - 成功
     * !=0 - 失败
     */
    public native static int Init(long sdk, String corpid, String secret);

    /**
     * 拉取聊天记录函数
     * Return值=0表示该API调用成功
     *
     * @param [in]  sdk				NewSdk返回的sdk指针
     * @param [in]  seq				从指定的seq开始拉取消息，注意的是返回的消息从seq+1开始返回，seq为之前接口返回的最大seq值。首次使用请使用seq:0
     * @param [in]  limit			一次拉取的消息条数，最大值1000条，超过1000条会返回错误
     * @param [in]  proxy			使用代理的请求，需要传入代理的链接。如：socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081
     * @param [in]  passwd			代理账号密码，需要传入代理的账号密码。如 user_name:passwd_123
     * @param [out] chatDatas		返回本次拉取消息的数据，slice结构体.内容包括errcode/errmsg，以及每条消息内容。
     * @return 返回是否调用成功
     * 0   - 成功
     * !=0 - 失败
     */
    public native static int GetChatData(long sdk, long seq, long limit, String proxy, String passwd, long timeout, long chatData);

    /**
     * 拉取媒体消息函数
     * Return值=0表示该API调用成功
     *
     * @param [in]  sdk				NewSdk返回的sdk指针
     * @param [in]  sdkFileid		从GetChatData返回的聊天消息中，媒体消息包括的sdkfileid
     * @param [in]  proxy			使用代理的请求，需要传入代理的链接。如：socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081
     * @param [in]  passwd			代理账号密码，需要传入代理的账号密码。如 user_name:passwd_123
     * @param [in]  indexbuf		媒体消息分片拉取，需要填入每次拉取的索引信息。首次不需要填写，默认拉取512k，后续每次调用只需要将上次调用返回的outindexbuf填入即可。
     * @param [out] media_data		返回本次拉取的媒体数据.MediaData结构体.内容包括data(数据内容)/outindexbuf(下次索引)/is_finish(拉取完成标记)
     * @return 返回是否调用成功
     * 0   - 成功
     * !=0 - 失败
     */
    public native static int GetMediaData(long sdk, String indexbuf, String sdkField, String proxy, String passwd, long timeout, long mediaData);

    /**
     * @param [in]  encrypt_key, getchatdata返回的encrypt_key
     * @param [in]  encrypt_msg, getchatdata返回的content
     * @param [out] msg, 解密的消息明文
     * @return 返回是否调用成功
     * 0   - 成功
     * !=0 - 失败
     * @brief 解析密文
     */
    public native static int DecryptData(long sdk, String encrypt_key, String encrypt_msg, long msg);

    public native static void DestroySdk(long sdk);

    public native static long NewSlice();

    /**
     * @return
     * @brief 释放slice，和NewSlice成对使用
     */
    public native static void FreeSlice(long slice);

    /**
     * @return 内容
     * @brief 获取slice内容
     */
    public native static String GetContentFromSlice(long slice);

    /**
     * @return 内容
     * @brief 获取slice内容长度
     */
    public native static int GetSliceLen(long slice);

    public native static long NewMediaData();

    public native static void FreeMediaData(long mediaData);

    /**
     * @return outindex
     * @brief 获取mediadata outindex
     */
    public native static String GetOutIndexBuf(long mediaData);

    /**
     * @return data
     * @brief 获取mediadata data数据
     */
    public native static byte[] GetData(long mediaData);

    public native static int GetIndexLen(long mediaData);

    public native static int GetDataLen(long mediaData);

    /**
     * @return 1完成、0未完成
     * @brief 判断mediadata是否结束
     */
    public native static int IsMediaDataFinish(long mediaData);

    static {
        String osName = System.getProperties().getProperty("os.name");
        File file = new File(System.getProperty("java.io.tmpdir"), "/library");
        log.info("当前操作系统：{} 获取tmpdir路径：{} 是否需要创建：{}", osName, file.getPath(), file.mkdirs());
        if (osName.toUpperCase().contains("WINDOWS")) {
            //打在Jar包中的文件无法使用System.load()来加载！！！
            log.info("Windows 加载Finance...");
            //加载顺序不要变
            try {
                File lib1 = new File(System.getProperty("java.io.tmpdir"), "/library/libcrypto-1_1-x64.dll");
                if (!lib1.exists()) {
                    FileCopyUtils.copy(Objects.requireNonNull(Finance.class.getResourceAsStream("/library/libcrypto-1_1-x64.dll")), new FileOutputStream(lib1));
                }
                System.load(lib1.getPath());
                File lib2 = new File(System.getProperty("java.io.tmpdir"), "/library/libssl-1_1-x64.dll");
                if (!lib2.exists()) {
                    FileCopyUtils.copy(Objects.requireNonNull(Finance.class.getResourceAsStream("/library/libssl-1_1-x64.dll")), new FileOutputStream(lib2));
                }
                System.load(lib2.getPath());
                File lib3 = new File(System.getProperty("java.io.tmpdir"), "/library/libcurl-x64.dll");
                if (!lib3.exists()) {
                    FileCopyUtils.copy(Objects.requireNonNull(Finance.class.getResourceAsStream("/library/libcurl-x64.dll")), new FileOutputStream(lib3));
                }
                System.load(lib3.getPath());
                File lib4 = new File(System.getProperty("java.io.tmpdir"), "/library/WeWorkFinanceSdk.dll");
                if (!lib4.exists()) {
                    FileCopyUtils.copy(Objects.requireNonNull(Finance.class.getResourceAsStream("/library/WeWorkFinanceSdk.dll")), new FileOutputStream(lib4));
                }
                System.load(lib4.getPath());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            log.info("Windows 加载Finance完成");
        } else {
            log.info("Linux 加载Finance...");
            try {
                File lib1 = new File(System.getProperty("java.io.tmpdir"), "/library/libWeWorkFinanceSdk_Java.so");
                if (!lib1.exists()) {
                    FileCopyUtils.copy(Objects.requireNonNull(Finance.class.getResourceAsStream("/library/libWeWorkFinanceSdk_Java.so")), new FileOutputStream(lib1));
                }
                System.load(lib1.getPath());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            log.info("Linux 加载Finance完成");
        }
    }

}
